package org.jeecg.modules.icms.job;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.icms.customs.entity.IcmsCustomsDetail;
import org.jeecg.modules.icms.customs.entity.IcmsCustomsHeader;
import org.jeecg.modules.icms.customs.mapper.IcmsCustomsHeaderMapper;
import org.jeecg.modules.icms.customs.service.impl.IcmsCustomsDetailServiceImpl;
import org.jeecg.modules.icms.customs.service.impl.IcmsCustomsHeaderServiceImpl;
import org.jeecg.modules.icms.invoice.entity.IcmsInvoiceDetail;
import org.jeecg.modules.icms.invoice.entity.IcmsInvoiceHeader;
import org.jeecg.modules.icms.invoice.mapper.IcmsInvoiceHeaderMapper;
import org.jeecg.modules.icms.invoice.service.impl.IcmsInvoiceDetailServiceImpl;
import org.jeecg.modules.icms.invoice.service.impl.IcmsInvoiceHeaderServiceImpl;
import org.jeecg.modules.icms.match.entity.IcmsInvoiceCustomsMatch;
import org.jeecg.modules.icms.match.enums.MatchStatusEnum;
import org.jeecg.modules.icms.match.mapper.IcmsInvoiceCustomsMatchMapper;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 开票单和报关单零件详情自动匹配定时任务
 *
 * @author 202304929
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class InvoiceAndCustomsMatchJob implements Job {

    @Resource
    private IcmsCustomsHeaderServiceImpl icmsCustomsHeaderService;
    @Resource
    private IcmsInvoiceHeaderServiceImpl icmsInvoiceHeaderService;
    @Resource
    private IcmsCustomsDetailServiceImpl icmsCustomsDetailService;
    @Resource
    private IcmsInvoiceDetailServiceImpl icmsInvoiceDetailService;
    @Resource
    private IcmsInvoiceCustomsMatchMapper icmsInvoiceCustomsMatchMapper;
    @Resource
    private IcmsInvoiceHeaderMapper icmsInvoiceHeaderMapper;
    @Resource
    private IcmsCustomsHeaderMapper icmsCustomsHeaderMapper;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        log.info(" Jeecg-Boot 开票单和报关单零件详情自动匹配定时任务 InvoiceAndCustomsMatchJob !  时间:{}", DateUtils.getTimestamp());

        //1-获取开票单和报关单状态为“未匹配”的相同的合同号
        List<IcmsCustomsHeader> customsHeaderList = icmsCustomsHeaderService.queryListWithoutMatch();
        List<IcmsInvoiceHeader> invoiceHeaderList = icmsInvoiceHeaderService.queryListWithoutMatch();
        List<String> matchContract = findMatchingContractNumbers(customsHeaderList, invoiceHeaderList);
        if (CollectionUtils.isEmpty(matchContract)) {
            System.out.println(DateUtils.getTimestamp());
            log.info("InvoiceAndCustomsMatchJob: 未找到相同合同号！ 时间：{}", DateUtils.getTimestamp());
        }
        //2-根据相同的合同号，找出合同号对应的开票单的零件详情和报关单零件详情做各种情况匹配
        List<IcmsInvoiceCustomsMatch> matchList = new ArrayList<>();
        matchContract.forEach(contractNo -> {
            //建一个新的Set,保存处理了的key,用于开票单零件多余报关单零件的情况
            Set<String> keysToDelete = new HashSet<>();

            Map<String, IcmsCustomsDetail> detailMap = icmsCustomsDetailService
                    .queryCustomsDetailInfoByContract(contractNo);
            Map<String, IcmsInvoiceDetail> invoiceMap = icmsInvoiceDetailService
                    .queryInvoiceDetailInfoByContract(contractNo);
            if (!detailMap.isEmpty()) {
                for (Map.Entry<String, IcmsCustomsDetail> customsDetailEntry : detailMap.entrySet()) {
                    IcmsInvoiceCustomsMatch match = new IcmsInvoiceCustomsMatch();
                    String partNo = customsDetailEntry.getKey();
                    IcmsCustomsDetail customsDetail = customsDetailEntry.getValue();
                    //如果key在invoiceMap中不存在，则匹配【开票单零件数量数据缺失，匹配状态为开票单无此件，报关状态为空白】
                    if (!invoiceMap.containsKey(partNo)) {
                        match.setInvoiceDetailId(null);
                        match.setWsdj(null);
                        match.setInvoiceQty(null);
                        match.setCustomsFlag(MatchStatusEnum.INVOICE_MISSING.getCustomsStatus());
                        match.setMatchStatus(MatchStatusEnum.INVOICE_MISSING.getMatchingSituation());
                    }
                    if (invoiceMap.containsKey(partNo)) {
                        IcmsInvoiceDetail invoiceDetail = invoiceMap.get(partNo);
                        match.setInvoiceDetailId(invoiceDetail.getInvoiceHeaderId());
                        match.setWsdj(invoiceDetail.getWsdj());
                        match.setInvoiceQty(invoiceDetail.getQty());
                        match.setCustomsFlag(MatchStatusEnum.determineMatchingStatus(invoiceDetail.getQty(),
                                customsDetail.getQty()).getCustomsStatus());
                        match.setMatchStatus(MatchStatusEnum.determineMatchingStatus(invoiceDetail.getQty(),
                                customsDetail.getQty()).getMatchingSituation());
                    }
                    match.setContractNo(customsDetail.getContractNo());
                    match.setCustomsDetailId(customsDetail.getId());
                    match.setCustomsQty(customsDetail.getQty());
                    match.setHsCode(customsDetail.getHsCode());
                    match.setExportCompany(customsDetail.getExportCountry());
                    match.setPartNo(customsDetail.getPartNo());
                    match.setPartName(customsDetail.getPartName());
                    match.setTaxRate(customsDetail.getTaxRate());
                    match.setMatchRemark(null);
                    matchList.add(match);
                    keysToDelete.add(partNo);
                }
                //移除invoiceMap已经处理的key
                invoiceMap.keySet().removeAll(keysToDelete);
                //如果移除key后的invoiceMap不为空,
                // 则invoiceMap剩下的匹配【报关单零件数量数据缺失，匹配情况为报关单无此件，报关状态是带出开票单对应的零件状态，要求报关或在要求不报关；】
                if (!invoiceMap.isEmpty()) {
                    for (Map.Entry<String, IcmsInvoiceDetail> otherDetailMap : invoiceMap.entrySet()) {
                        IcmsInvoiceCustomsMatch otherMatch = new IcmsInvoiceCustomsMatch();
                        IcmsInvoiceDetail detail = otherDetailMap.getValue();
                        otherMatch.setInvoiceDetailId(detail.getInvoiceHeaderId());
                        otherMatch.setContractNo(contractNo);
                        otherMatch.setCustomsDetailId(null);
                        otherMatch.setHsCode(null);
                        otherMatch.setExportCompany(null);
                        otherMatch.setPartNo(detail.getPartNo());
                        otherMatch.setPartName(detail.getPartName());
                        otherMatch.setWsdj(detail.getWsdj());
                        otherMatch.setTaxRate(detail.getTaxRate());
                        otherMatch.setInvoiceQty(detail.getQty());
                        otherMatch.setCustomsQty(null);
                        otherMatch.setCustomsFlag(convertString(detail.getCustomsFlag()));
                        otherMatch.setMatchStatus(MatchStatusEnum.CUSTOMS_MISSING.getMatchingSituation());
                        otherMatch.setMatchRemark(null);
                        matchList.add(otherMatch);
                    }
                }
                //3-插入matchList，修改开票单头表，报关单头表匹配状态为【已匹配】
                afterProcess(matchList, contractNo);
            }
            log.info("InvoiceAndCustomsMatchJob: 合同号：{} 匹配完成！时间：{}", contractNo, DateUtils.getTimestamp());
        });
        log.info("InvoiceAndCustomsMatchJob: 所有合同号处理完成等，时间：{}", DateUtils.getTimestamp());
    }

    public static String convertString(String a) {
        if ("0".equals(a)){
            return "要求不报关";
        }
        if ("1".equals(a)){
            return "要求报关";
        }
        return null;
    }

    public void afterProcess(List<IcmsInvoiceCustomsMatch> matchList, String contractNo) {
        if (!CollectionUtils.isEmpty(matchList)) {
            matchList.forEach(match -> icmsInvoiceCustomsMatchMapper.insert(match));
        }
        //修改开票单合同号的匹配状态
        LambdaUpdateWrapper<IcmsInvoiceHeader> invoiceUpdate = new LambdaUpdateWrapper<>();
        invoiceUpdate.eq(IcmsInvoiceHeader::getContractNo, contractNo)
                .set(IcmsInvoiceHeader::getMatchFlag, "1");
        icmsInvoiceHeaderMapper.update(null, invoiceUpdate);
        //修改报关单合同号匹配状态
        LambdaUpdateWrapper<IcmsCustomsHeader> customsUpdate = new LambdaUpdateWrapper<>();
        customsUpdate.eq(IcmsCustomsHeader::getContractNo, contractNo)
                .set(IcmsCustomsHeader::getMatchFlag, "1");
        icmsCustomsHeaderMapper.update(null, customsUpdate);
    }

    public static List<String> findMatchingContractNumbers(List<IcmsCustomsHeader> customsHeaders,
                                                           List<IcmsInvoiceHeader> invoiceHeaders) {
        // 将两个列表转换为Set，以便快速查找
        Set<String> customsContractNumbers = customsHeaders.stream()
                .map(IcmsCustomsHeader::getContractNo)
                .collect(Collectors.toSet());

        Set<String> invoiceContractNumbers = invoiceHeaders.stream()
                .map(IcmsInvoiceHeader::getContractNo)
                .collect(Collectors.toSet());

        // 找出两个集合中共有的contractNo
        Set<String> matchingContractNumbers = customsContractNumbers.stream()
                .filter(invoiceContractNumbers::contains)
                .collect(Collectors.toSet());

        // 将结果转换回List
        return new ArrayList<>(matchingContractNumbers);
    }
}
